home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / vbcc.lha / vbcc / pasm / directives.c next >
C/C++ Source or Header  |  1998-02-17  |  25KB  |  1,089 lines

  1. /* $VER: pasm directives.c V0.8 (14.02.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.8 (14.02.98) phx
  16.  *      Alignment list for each section. This fixes the problems
  17.  *      with optimizations.
  18.  * v0.6 (30.10.97) phx
  19.  *      The names of macros will be converted to lower case (otherwise,
  20.  *      they would remain inaccessible ;)
  21.  * v0.5 (12.10.97) phx
  22.  *      .set directive is allowed multiple times on the same symbol.
  23.  *      If a .set-assignment can't be resolved in pass 1, the symbol
  24.  *      is no longer undefined, but defined with an absolute default
  25.  *      value of '1'. So .ifdef will work correctly.
  26.  *      .globl directive declares unknown symbols in pass 1 as
  27.  *      externally defined. If the symbol is defined later in the
  28.  *      source, it will be made global by add_symbol()/tables.c.
  29.  * v0.4 (29.04.97) phx
  30.  *      .new_section sets type of section-symbol to SYMI_SECTION.
  31.  *      New directives: .baserel
  32.  * v0.3 (10.04.97) phx
  33.  *      Some vbcc-specific changes.
  34.  * v0.2 (25.03.97) phx
  35.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  36.  *      or ELF output format may be selected. ELF is default for all
  37.  *      currently supported platforms. PPCasm supports nine different
  38.  *      relocation types (there are much more...).
  39.  *      Compiles and works also under NetBSD/amiga (68k).
  40.  *      Changed function declaration to 'new style' in all sources
  41.  *      (to avoid problems with '...' for example).
  42.  *      Floating pointer support. New directives: .fail, .ident, .file,
  43.  *      .float, .ufloat, .double, .udouble, .local.
  44.  * v0.1 (11.03.97) phx
  45.  *      First test version with all PowerPC instructions and most
  46.  *      important directives. Only raw, absolute output.
  47.  *      .ident and .file directives are supported, but have no effect.
  48.  *      Especially floating point directives are missing.
  49.  * v0.0 (21.02.97) phx
  50.  *      File created.
  51.  */
  52.  
  53.  
  54. #define DIRECTIVES_C
  55. #include "ppcasm.h"
  56.  
  57.  
  58. void activate_section(struct GlobalVars *,struct Section *);
  59. void alignment(struct GlobalVars *,unsigned long);
  60. char escchar(char);
  61.  
  62. static void start_section(struct GlobalVars *,struct ParsedLine *pl,bool);
  63. static char *section_attributes(struct GlobalVars *,char *,uint8 *,
  64.                                 uint8 *,uint8 *,uint8 *);
  65. static void _uahalf(struct GlobalVars *,struct ParsedLine *);
  66. static void _uaword(struct GlobalVars *,struct ParsedLine *);
  67. static void uafloat(struct GlobalVars *,struct ParsedLine *,bool);
  68. static void ifeqs(struct GlobalVars *,struct ParsedLine *,int);
  69. static void ifdef(struct GlobalVars *,struct ParsedLine *,bool);
  70.  
  71.  
  72.  
  73. static void _new_section(struct GlobalVars *gv,struct ParsedLine *pl)
  74. {
  75.   start_section(gv,pl,1);
  76. }
  77.  
  78.  
  79. static void _section(struct GlobalVars *gv,struct ParsedLine *pl)
  80. {
  81.   start_section(gv,pl,0);
  82. }
  83.  
  84.  
  85. static void start_section(struct GlobalVars *gv,struct ParsedLine *pl,
  86.                           bool force_new)
  87. /* define a new section with new attributes or reactivate a */
  88. /* previously defined one */
  89. {
  90.   struct Section *nexts,*sec = (struct Section *)gv->sectionlist.first;
  91.   struct Symbol *sym;
  92.   struct AlignPoint *ap;
  93.   char *s,*name;
  94.   uint8 type,flags,protection,alignment;
  95.  
  96.   s = getarg(gv,pl->operand);  /* section's name */
  97.   name = remquotes(gv->strbuf);
  98.  
  99.   while (nexts = (struct Section *)sec->n.next) {
  100.     if (!strcmp(name,sec->name)) {
  101.  
  102.       if (force_new) {  /* overwrite an old section with the same name? */
  103.         sprintf(gv->strbuf,"%s_%08lx",sec->name,(unsigned long)sec);
  104.         name = sec->name;
  105.         sec->name = allocstring(gv->strbuf);
  106.         break;
  107.       }
  108.  
  109.       else {  /* reactivate old section with the same name */
  110.         s = section_attributes(gv,s,&type,&flags,&protection,&alignment);
  111.         if (type != ST_UNDEFINED)  /* attributes specified? */
  112.           if (sec->type!=type || sec->flags!=flags ||
  113.               sec->protection!=protection || sec->alignment!=alignment)
  114.             error(16);  /* section attributes don't match */
  115.         pl->type = OT_SECTION;
  116.         pl->opcode = (void *)sec;
  117.         activate_section(gv,sec);
  118.         checkEOL(s);
  119.         return;
  120.       }
  121.  
  122.     }
  123.     sec = nexts;
  124.   }
  125.  
  126.   /* create a new section */
  127.   sec = alloczero(sizeof(struct Section));
  128.   sec->name = allocstring(name);
  129.   s = section_attributes(gv,s,&sec->type,&sec->flags,&sec->protection,
  130.                          &sec->alignment);
  131.   if (sec->type == ST_UNDEFINED) {  /* set default attributes */
  132.     sec->type = ST_DATA;
  133.     sec->protection = SP_READ|SP_WRITE;
  134.     sec->alignment = 2;
  135.   }
  136.   initlist(&sec->reloclist);
  137.   initlist(&sec->xreflist);
  138.   ap = alloc(sizeof(struct AlignPoint));
  139.   ap->next = NULL;
  140.   ap->offset = ap->gap = 0;
  141.   ap->val = 1 << sec->alignment;
  142.   sec->first_align = sec->current_align = ap;
  143.   addtail(&gv->sectionlist,&sec->n);
  144.   pl->type = OT_SECTION;
  145.   pl->opcode = (void *)sec;
  146.   activate_section(gv,sec);
  147.   sym = add_symbol(gv,sec->name,SYM_RELOC,0);
  148.   sym->info = SYMI_SECTION;
  149.   checkEOL(s);
  150. }
  151.  
  152.  
  153. void activate_section(struct GlobalVars *gv,struct Section *sec)
  154. {
  155.   gv->csect = sec;  /* set active section */
  156.   gv->lcsym->relsect = sec;
  157.   gv->lcsym->value = sec->pc;
  158. }
  159.  
  160.  
  161. static char *section_attributes(struct GlobalVars *gv,char *s,uint8 *t,
  162.                                 uint8 *f,uint8 *p,uint8 *a)
  163. /* fill in section attributes, if specified */
  164. {
  165.   char c,*attr;
  166.  
  167.   *t = ST_UNDEFINED;
  168.   *f = *p = *a = 0;
  169.   s = skipspaces(s);
  170.   if (*s) {
  171.     if (*s == ',') {
  172.       s = skipspaces(++s);
  173.       s = getarg(gv,s);
  174.       c = *gv->strbuf;
  175.       if (c=='\"' || c=='\'') {
  176.         attr = remquotes(gv->strbuf);
  177.         while (c = *attr++) {
  178.           switch (c) {
  179.             /* contents type */
  180.             case 'c':
  181.               *t = ST_CODE;
  182.               break;
  183.             case 'd':
  184.               *t = ST_DATA;
  185.               break;
  186.             case 'u':
  187.               *t = ST_UDATA;
  188.               *f |= SF_UNINITIALIZED;
  189.               break;
  190.             case 'i':
  191.               *t = ST_STRUCT;
  192.               *f |= SF_DISCARD|SF_UNINITIALIZED;
  193.               break;
  194.             /* protection */
  195.             case 'r':
  196.               *p |= SP_READ;
  197.               break;
  198.             case 'w':
  199.               *p |= SP_WRITE;
  200.               break;
  201.             case 'x':
  202.               *p |= SP_EXEC;
  203.               break;
  204.             case 's':
  205.               *p |= SP_SHARE;
  206.               break;
  207.             case 'n': /* remove and discard currently not supported */
  208.             case 'R':
  209.               break;
  210.             default:
  211.               if (c>='0' && c <='6')
  212.                 *a = (uint8)(c-'0');  /* alignment */
  213.               else
  214.                 error(15,c);  /* illegal section attribute */
  215.               break;
  216.           }
  217.         }
  218.       }
  219.       else
  220.         error(14);  /* string constant expected */
  221.     }
  222.     else if (*s != '#')
  223.       error(12);  /* colon expected */
  224.   }
  225.   return (s);
  226. }
  227.  
  228.  
  229. static void _set(struct GlobalVars *gv,struct ParsedLine *pl)
  230. {
  231.   char *s = getsymbol(gv,pl->operand);
  232.   struct Expression exp;
  233.   struct Section *cs;
  234.   char setname[STRBUFSIZE];
  235.   struct Symbol *sym;
  236.  
  237.   if (*gv->strbuf) {
  238.     strcpy(setname,gv->strbuf);
  239.     if (s = check_comma(s)) {
  240.       s = eval_expression(gv,&exp,s);
  241.       if (exp.type != SYM_UNDEF) {
  242.         if (exp.type != SYM_EXTERN) {
  243.           if (exp.type == SYM_RELOC) {
  244.             if (exp.reloctype == R_PPC_ADDR32) {
  245.               if (sym = search_symbol(gv,setname)) {
  246.                 sym->value = exp.value;
  247.                 sym->type = SYM_RELOC;
  248.                 sym->relsect = exp.symbol->relsect;
  249.               }
  250.               else {
  251.                 cs = gv->csect;
  252.                 gv->csect = exp.symbol->relsect;
  253.                 add_symbol(gv,setnam